/**
 * This class represents the main GUI that we will create in the game. This GUI
 * houses all the in game components like the ShortRangeChart, Shipyard,
 * Marketplace, and SolarSystem information.
 * 
 * @author Araya Zaesim, Stanley Ayzenberg, Michelle Partogi, Adam Perez
 * @version 1.0
 */

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;


import java.util.List;
import java.util.Random;

import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.BorderLayout;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
import javax.swing.SwingConstants;
import java.awt.Component;
import javax.swing.Box;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.swing.BoxLayout;

/**
 * @author Araya Zaeism, Adam Perez, Stanley Ayzenberg, Michelle Partogi
 * @version 1.0
 */
public class SpaceTraderGui {

	/**
	 * Field frame.
	 */
	private JFrame frame;

	/**
	 * Field player.
	 */
	private Player player;

	/**
	 * Field universe.
	 */
	private List<SolarSystem> universe;

	/**
	 * Field lblPlayername.
	 */
	private JLabel lblPlayername;

	/**
	 * Field mainPanel.
	 */
	private JPanel mainPanel;

	/**
	 * Field chartPanel.
	 */
	private ShortRangeChart chartPanel;

	/**
	 * Field northPanel.
	 */
	private JPanel northPanel;

	/**
	 * Field topMenuPanel.
	 */
	private JPanel topMenuPanel;

	/**
	 * Field btnNewGame.
	 */
	private JButton btnNewGame;

	/**
	 * Field btnSaveGame.
	 */
	private JButton btnSaveGame;

	/**
	 * Field btnLoadGame.
	 */
	private JButton btnLoadGame;

	/**
	 * Field tabPanel_1.
	 */
	private JPanel tabPanel_1;

	/**
	 * Field tabPanel_2.
	 */
	private JPanel tabPanel_2;

	/**
	 * Field infoPanel.
	 */
	private JPanel infoPanel;

	/**
	 * Field lblSolarSystem.
	 */
	private JLabel lblSolarSystem;

	/**
	 * Field lblCredits.
	 */
	private JLabel lblCredits;

	/**
	 * Field tabbedPane.
	 */
	private JTabbedPane tabbedPane;

	/**
	 * Field curSSPanel_1.
	 */
	private JPanel curSSPanel_1;

	/**
	 * Field systemPanel.
	 */
	private JPanel systemPanel;

	/**
	 * Field shipyardPanel.
	 */
	private Shipyard shipyardPanel;

	/**
	 * Field rand.
	 */
	private Random rand;

	/**
	 * Field currentSystem.
	 */
	private SolarSystem currentSystem = null;

	/**
	 * Field targetSystem.
	 */
	private SolarSystem targetSystem = null;

	/**
	 * Field mpLogic.
	 */
	private MarketPlaceLogic mpLogic;

	/**
	 * Field buyPrices.
	 */
	private int[] buyPrices = new int[10];

	/**
	 * Field sellPrices.
	 */
	private int[] sellPrices = new int[10];

	/**
	 * Field label_1.
	 */
	private JLabel label_1;

	/**
	 * Field label_2.
	 */
	private JLabel label_2;

	/**
	 * Field gamePanel.
	 */
	private JPanel gamePanel;

	/**
	 * Field bg.
	 */
	private JLabel bg;

	/**
	 * Field tarSystemInfo.
	 */
	private SystemPanel tarSystemInfo;

	/**
	 * Field currSystemInfo.
	 */
	private SystemPanel currSystemInfo;

	/**
	 * Field btnWarp.
	 */
	private JButton btnWarp;

	/**
	 * Field lblFuelLevel.
	 */
	private JLabel lblFuelLevel;

	/**
	 * Method getCurrentSystem.
	 * @return SolarSystem 
	 */
	public SolarSystem getCurrentSystem() {
		return currentSystem;
	}

	/**
	 * Method setCurrentSystem.
	 * @param currentSystem SolarSystem
	 */
	public void setCurrentSystem(SolarSystem currentSystem) {
		this.currentSystem = currentSystem;
	}

	/**
	 * Field marketplace.
	 */
	private Marketplace marketplace;

	/**
	 * Field saveload.
	 */
	private SaveLoad saveload;
	
	/**
	 * toString method.
	 * @return String 
	 */
	public String toString() {
		return "";
	}

	/**
	 * Launch the application.
	 * @param args String[]
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					final SpaceTraderGui window = new SpaceTraderGui();
					window.getFrame().setVisible(true);

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application. Also creates the universe with allSystems.
	 */
	public SpaceTraderGui() {
		initialize();
	}

	/**
	 * A getter for the ShortRangeChart in the GUI.
	 * @return The chart. 
	 */
	public ShortRangeChart getChartPanel() {
		return chartPanel;
	}

	/**
	 * A setter for the Short Range Chart in the GUI.
	 * @param c The ShortRangeChart
	 */
	public void setChartPanel(ShortRangeChart c) {
		chartPanel = c;
		chartPanel.updateRange();
		chartPanel.repaint();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		rand = new Random();
		setFrame(new JFrame());
		// frame.setResizable(false);
		getFrame().setPreferredSize(new Dimension(1300, 1200));
		getFrame().setBounds(1200, 100, 950, 650);
		getFrame().setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		getFrame().getContentPane().setLayout(new BorderLayout(0, 0));

		mainPanel = new JPanel();
		getFrame().getContentPane().add(mainPanel, BorderLayout.CENTER);
		mainPanel.setLayout(new BorderLayout(0, 0));

		northPanel = new JPanel();
		mainPanel.add(northPanel, BorderLayout.NORTH);
		northPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
		northPanel.setBackground(new Color(3, 2, 4));

		topMenuPanel = new JPanel();
		northPanel.add(topMenuPanel);
		topMenuPanel.setBackground(new Color(3, 2, 4));

		saveload = new SaveLoad(this);

		btnNewGame = new JButton("New Game");
		btnNewGame.addActionListener(new ActionListener() {

			/*
			 * Creates a config window when New Game is pressed so that a user
			 * can enter skill points, name, and choose a difficulty.
			 */
			public void actionPerformed(ActionEvent e) {
				new ConfigWindow(getGui());
			}
		});
		topMenuPanel.add(btnNewGame);

		btnSaveGame = new JButton("Save Game");
		btnSaveGame.addActionListener(new ActionListener() {
			/*
			 * Saves the game
			 */
			public void actionPerformed(ActionEvent e) {
				saveload.saveGame();
			}
		});
		topMenuPanel.add(btnSaveGame);

		btnLoadGame = new JButton("Load Game");
		btnLoadGame.addActionListener(new ActionListener() {
			/*
			 * Loads an existing game
			 */
			public void actionPerformed(ActionEvent e) {
				saveload.loadGame();
			}
		});
		topMenuPanel.add(btnLoadGame);

		gamePanel = new JPanel();
		mainPanel.add(gamePanel, BorderLayout.CENTER);
		gamePanel.setLayout(new BoxLayout(gamePanel, BoxLayout.Y_AXIS));

		bg = new JLabel(new ImageIcon("intro.jpg"));
		bg.setPreferredSize(new Dimension(900, 900));
		gamePanel.add(bg);

	}

	/**
	 * A method to start the game after a player hits new game.
	 * @param newPlayer
	 *            The player object created using the specifications that the
	 *            player inputted in the config window.
	 */
	public void startGame(Player newPlayer) {
		rand = new Random();
		if (universe == null) {
			gamePanel.remove(bg);
		}
		else {
			mainPanel.remove(gamePanel);
			gamePanel = new JPanel();
			mainPanel.add(gamePanel, BorderLayout.CENTER);
			gamePanel.setLayout(new BoxLayout(gamePanel, BoxLayout.Y_AXIS));
			currentSystem = null;
			targetSystem = null;

		}
		final Universe un = new Universe();
		this.universe = un.getSystems();

		infoPanel = new JPanel();
		gamePanel.add(infoPanel);

		lblSolarSystem = new JLabel("Solar System: ");
		infoPanel.add(lblSolarSystem);

		final Component horizontalStrut = Box.createHorizontalStrut(60);
		infoPanel.add(horizontalStrut);
		lblPlayername = new JLabel("Player: ");
		infoPanel.add(lblPlayername);
		lblPlayername.setHorizontalAlignment(SwingConstants.RIGHT);

		final Component horizontalStrut_1 = Box.createHorizontalStrut(60);
		infoPanel.add(horizontalStrut_1);

		lblCredits = new JLabel("Credits: ");
		infoPanel.add(lblCredits);

		tabPanel_1 = new JPanel();
		tabPanel_2 = new JPanel();

		tabbedPane = new JTabbedPane(javax.swing.SwingConstants.TOP);
		gamePanel.add(tabbedPane);
		tabbedPane.addTab("Marketplace", null, tabPanel_1, null);
		tabbedPane.addTab("Shipyard", null, tabPanel_2, null);

		tabPanel_1.setLayout(new BoxLayout(tabPanel_1, BoxLayout.Y_AXIS));

		curSSPanel_1 = new JPanel();
		curSSPanel_1.setPreferredSize(new Dimension(600, 350));
		tabPanel_1.add(curSSPanel_1);
		curSSPanel_1.setLayout(new BoxLayout(curSSPanel_1, BoxLayout.X_AXIS));

		label_1 = new JLabel("");
		curSSPanel_1.add(label_1);

		label_2 = new JLabel("");
		curSSPanel_1.add(label_2);
		/**
		 * Makes system Panel!!!
		 */

		systemPanel = new JPanel();
		tabPanel_1.add(systemPanel);
		systemPanel.setLayout(new GridLayout(1, 3, 0, 0));

		currSystemInfo = new SystemPanel("Current");
		systemPanel.add(currSystemInfo);

		tarSystemInfo = new SystemPanel("Target");
		systemPanel.add(tarSystemInfo);
		System.out.println(universe);
		if (currentSystem == null) {
			currentSystem = universe.get(rand.nextInt(universe.size()));
			currSystemInfo.updatePanel(currentSystem);
			lblSolarSystem.setText("System: " + currentSystem.getName());
		}
		final JPanel holder = new JPanel();
		systemPanel.add(holder);
		final JPanel fuelWarp = new JPanel();
		fuelWarp.setLayout(new BoxLayout(fuelWarp, BoxLayout.Y_AXIS));

		btnWarp = new JButton("Warp");
		btnWarp.setEnabled(false);
		fuelWarp.add(btnWarp);

		lblFuelLevel = new JLabel("Fuel Level: ");
		fuelWarp.add(lblFuelLevel);
		systemPanel.add(fuelWarp);

		setPlayer(newPlayer);

		shipyardPanel = new Shipyard(this);
		tabPanel_2.add(shipyardPanel);

		/**
		 * Moves to target system
		 */
		btnWarp.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				player.getShip().updateFuelFromTravel(currentSystem,
						targetSystem, player);
				currentSystem = targetSystem;// need to go after fuel update
				marketplace.newMarketPlace(currentSystem); // needs to go after
															// system swap
				updateSolarSystem();
				currSystemInfo.updatePanel(targetSystem);
				currSystemInfo.setEvent(marketplace.getEvent());
				tarSystemInfo.clear();
				lblFuelLevel.setText("Fuel Level: "
						+ player.getShip().getFuel() + "/"
						+ player.getShip().getMaxFuel());
				targetSystem = null;
				btnWarp.setEnabled(false);
				lblSolarSystem.setText("System: " + currentSystem.getName());
				chartPanel.setCurrSystem(currentSystem);
				chartPanel.updateRange();
				chartPanel.repaint();
				shipyardPanel.updatePanel();
				System.out.println("btnWarp");
			}
		});// end action listener
	}

	/**
	 * Gets the JButton for the warping button.
	 * @return The button that allows players to warp. 
	 */
	public JButton getBtnWarp() {
		return btnWarp;
	}

	/**
	 * A method to get the shipyard panel contained in the GUI.
	 * @return The panel for shipyard. */
	public Shipyard getShipyardPanel() {
		return shipyardPanel;
	}

	/**
	 * A setter for the shipyard panel in the GUI.
	 * @param shipyardPanel
	 *            The panel to place into the GUI.
	 */
	public void setShipyardPanel(Shipyard shipyardPanel) {
		this.shipyardPanel = shipyardPanel;
	}

	/**
	 * Sets the data of the player within the GUI by getting the player data of
	 * the object created by users.
	 * @param player
	 *            The player object for the GUI
	 */
	public void setPlayer(Player player) {
		this.player = player;
		lblPlayername.setText("Player: " + player.getName());
		lblCredits.setText("Credits: " + player.getCredits());
		createMarketPlace(player);
	}

	/**
	 * Creates the market place so the player can buy/sell goods.
	 * @param player
	 *            The player object.
	 */
	public void createMarketPlace(Player player) {
		if (marketplace != null) {
			curSSPanel_1.remove(marketplace);
		}
		marketplace = new Marketplace(player, currentSystem, this);
		curSSPanel_1.add(marketplace);
		makeShortRangeChart();
	}

	/**
	 * This method creates the Short Range Chart inside of the GUI.
	 */
	public void makeShortRangeChart() {
		if (chartPanel != null) {
			curSSPanel_1.remove(chartPanel);
		}
		chartPanel = new ShortRangeChart(universe, this, player);
		lblFuelLevel.setText("Fuel Level: " + player.getShip().getFuel() + "/"
				+ player.getShip().getMaxFuel());
		chartPanel.setLayout(new GridLayout(2, 0, 4, 0));
		chartPanel.setCurrSystem(currentSystem);
		curSSPanel_1.add(chartPanel, BorderLayout.EAST);
		currSystemInfo.setEvent(marketplace.getEvent());
	}

	/**
	 * Gets data of the player
	 * 
	
	 * @return The player object */
	public Player getPlayer() {
		return player;
	}

	/**
	 * This method sets the credits label in the GUI. DOES NOT SET CREDITS OF
	 * THE PLAYER.
	 * 
	 * @param credits
	 *            The number of credits the player has.
	 */
	public void setCredits(int credits) {
		lblCredits.setText("Credits: " + credits);
	}

	/**
	 * Updates the target system information in the GUI after clicking a system.
	 * 
	 * @param system
	 *            The system the user has clicked on.
	 */
	public void updateTargetSystem(SolarSystem system) {
		targetSystem = system;
		// btnWarp.setEnabled(true);
		tarSystemInfo.update(currentSystem, targetSystem);
		chartPanel.setTarSystem(targetSystem);
		if (chartPanel.equalsInRange(currentSystem, system)) {
			btnWarp.setEnabled(true);
		} else {
			btnWarp.setEnabled(false);
		}
	}

	/**
	 * This method updates the whole solar system after the player has warped or
	 * has clicked on different planets.
	 */
	public void updateSolarSystem() {
		lblSolarSystem.setText("System: " + currentSystem.getName());
		chartPanel.setCurrSystem(currentSystem);
		chartPanel.updateRange();
		chartPanel.repaint();
		String event;
		if (rand.nextInt(100) < 10) {
			final int index = rand.nextInt(7);
			final String[] array = { "Lack of Workers", "Boredom", "Plague", "War",
					"Cropfail", "Cold", "Drought" };
			event = array[index];
		} else {
			event = "None";
		}
		mpLogic = new MarketPlaceLogic(currentSystem, event);
		buyPrices = mpLogic.buyPrices();
		sellPrices = mpLogic.sellPrices();
	}

	/**
	 * Updates the label for the fuel level after warping.
	 */
	public void updateLabels() {
		lblFuelLevel.setText("Fuel Level: " + player.getShip().getFuel() + "/"
				+ player.getShip().getMaxFuel());
	}

	/**
	 * Loads all the data created by the save.
	 * 
	 * @param player
	 *            The saved player.
	 * @param currentSystem
	 *            The system the player was on.
	 * @param universe
	 *            The layout of the universe.
	 * @param buyPrices
	 *            The prices of the goods in their current system.
	 * @param sellPrices
	 *            The prices they could sell their goods for.
	 */
	public void loadData(Player player, SolarSystem currentSystem,
			List<SolarSystem> universe, int[] buyPrices, int[] sellPrices) {
		if (this.universe == null) {
			startGame(player);
		} else {
			setPlayer(player);
		}
		setCurrentSystem(currentSystem);
		this.universe = universe;
		updateSolarSystem();
		shipyardPanel.setPlayer(player);
		shipyardPanel.updatePanel();
		// this.chartPanel = new ShortRangeChart(universe, this, player);
		makeShortRangeChart();
		marketplace.setBuyPrices(buyPrices);
		marketplace.setSellPrices(sellPrices);
		marketplace.setCurrentSystem(currentSystem);
		marketplace.updateMarketPlace(player);
	}

	/**
	 * A getter for the GUI itself (and all of the data within it)
	 * 
	
	 * @return The GUI */
	public SpaceTraderGui getGui() {
		return this;
	}

	/**
	 * A getter for the Universe.
	 * 
	
	 * @return An ArrayList of the solar systems. */
	public List<SolarSystem> getUniverse() {
		return universe;
	}

	/**
	 * Sets the universe to be used in the game.
	 * 
	 * @param universe
	 *            The list of solar systems.
	 */
	public void setUniverse(List<SolarSystem> universe) {
		this.universe = universe;
	}

	/**
	 * Getter for the marketplace that the player buys or sells on.
	 * 
	
	 * @return The marketplace. */
	public Marketplace getMarketplace() {
		return marketplace;
	}

	/**
	 * Setter for the marketplace that the player buys or sells on.
	 * 
	 * @param marketplace
	 *            The marketplace.
	 */
	public void setMarketplace(Marketplace marketplace) {
		this.marketplace = marketplace;
	}

	/**
	 * Method getFrame.
	
	 * @return JFrame */
	public JFrame getFrame() {
		return frame;
	}

	/**
	 * Method setFrame.
	 * @param frame JFrame
	 */
	public void setFrame(JFrame frame) {
		this.frame = frame;
	}
	
	/**
	 * Method getTargetSystem.
	
	 * @return SolarSystem */
	public SolarSystem getTargetSystem() {
		return targetSystem;
	}
	
	/**
	 * Method getLblCredits.
	
	 * @return lblCredits */
	public JLabel getLblCredits() {
		return lblCredits;
	}
	
	/**
	 * Method setTargetSystem.
	
	 * @param targetSystem
	 * 				The solar system player clicks on.
	 */
	public void setTargetSystem(SolarSystem targetSystem) {
		this.targetSystem = targetSystem;
		updateTargetSystem(targetSystem);
	}
}
